import { menu } from '../../../app/decorator';

const { ccclass, property } = cc._decorator;

@ccclass
@menu(__filename)
export default class InitPrefab extends cc.Component {
    @property
    protected _target: cc.Node = null;
    @property({
        type: cc.Node,
        tooltip: '默认是本节点'
    })
    get target() {
        if (this._target && !this._target.isValid) {
            this._target = null;
        }
        return this._target || this.node;
    }
    set target(value) {
        this._target = value;
    }

    @property
    private _itemPre: cc.Prefab = null;
    @property(cc.Prefab)
    get itemPre() { return this._itemPre; }
    set itemPre(value) {
        this._itemPre = value;

        if (this._itemPre && this._initCom) {
            this.itemComName = this._itemPre.name;
            this.itemComFun = 'init';
        } else {
            this.itemComName = '';
            this.itemComFun = '';
        }
    }

    @property
    private _initCom: boolean = null;
    @property
    get initCom() { return this._initCom; }
    set initCom(value) {
        this._initCom = value;

        if (this._itemPre && this._initCom) {
            this.itemComName = this._itemPre.name;
            this.itemComFun = 'init';
        } else {
            this.itemComName = '';
            this.itemComFun = '';
        }
    }

    @property({
        visible: function () {
            return !!this.initCom;
        },
        tooltip: '预制的脚本名字'
    })
    itemComName: string = '';

    @property({
        visible: function () {
            return !!this.initCom;
        },
        tooltip: '调用预制脚本的方法名'
    })
    itemComFun: string = '';

    @property
    _updateLayout: boolean = false;
    @property({
        visible() {
            const layout = this.getComponent(cc.Layout);
            return layout && !layout.enabled;
        },
        tooltip: '调用初始化函数是更新layout'
    })
    get updateLayout() {
        if (this._updateLayout) {
            const layout = this.getComponent(cc.Layout);
            this._updateLayout = !!layout && !layout.enabled;
        }
        return this._updateLayout;
    }
    set updateLayout(value) {
        this._updateLayout = !!value;
    }

    private _pool: cc.NodePool = null;

    _getPool() {
        if (!this._pool) {
            this._pool = new cc.NodePool(this.itemComName);
        }
        return this._pool;
    }

    _getNode() {
        let node;
        if (this._getPool().size() > 0) {
            node = this._pool.get();
        } else {
            node = cc.instantiate(this.itemPre);
        }
        return node;
    }

    _putNode(node) {
        this._getPool().put(node);
    }

    _init(node, index, data) {
        if (this.initCom && this.itemComName && this.itemComFun) {
            node.getComponent(this.itemComName)[this.itemComFun](index, data);
        }
    }

    init(num: number, data?: any, handleCB?: Function) {
        const content = this.target || this.node;
        const children = content.children;

        let index = 0;
        let node = null;
        for (; index < num; index++) {
            node = children[index];
            if (node) {
                this._init(node, index, data);
            } else {
                node = this._getNode();
                node.parent = content;
                this._init(node, index, data);
            }

            handleCB && handleCB(node, index, data);
        }

        for (let i = children.length - 1; i >= index; i--) {
            this._putNode(children[i]);
        }

        const layout = this.getComponent(cc.Layout);
        if (this.updateLayout) {
            layout.enabled = true;
            layout.updateLayout();
            layout.enabled = false;
        }
    }

    clear() {
        const node = this.target || this.node;
        const children = node.children;
        for (let i = children.length - 1; i >= 0; i--) {
            this._putNode(children[i]);
        }
    }
}
